home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / strategy / xpat2-1.000 / xpat2-1 / xpat2-1.04 / etc / wavplay.c < prev    next >
C/C++ Source or Header  |  1994-09-27  |  7KB  |  267 lines

  1. /****************************************************************/
  2. /*                                */
  3. /*    wavplay.c                        */
  4. /*    Sample .WAV player for xpat2.                */
  5. /*    1994 by M. Bischoff                    */
  6. /*                                */
  7. /*    To use this with xpat2, do the following:        */
  8. /*    1) compile this program with                */
  9. /*       $ gcc -s -O wavplay.c -o wavplay            */
  10. /*    2) Then, make a named pipe /tmp/audio:            */
  11. /*       $ mknod /tmp/audio p                    */
  12. /*    3) Compile the module X-sound_SUN.c with the        */
  13. /*       additional option -DAUDIO_DEVICE=\"/tmp/audio\"    */
  14. /*       to redirect sound output to the named pipe.        */
  15. /*     4) start the WAV-player:                */
  16. /*       $ wavplay &                        */
  17. /*    5) substitute all .au files with .wav files, but keep   */
  18. /*       the original name.                    */
  19. /*    6) start xpat2:                        */
  20. /*       $ xpat2                        */
  21. /*    Have fun! (and don't forget to kill wavplay later)    */
  22. /*                                */
  23. /****************************************************************/
  24.  
  25. #include <sys/soundcard.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <unistd.h>
  31. #include <fcntl.h>
  32.  
  33. struct wavfmt {
  34.     char c_RIFF[4];
  35.     long len_file;
  36.     char c_WAVE[4];
  37.  
  38.     char c_fmt[4];
  39.     long len_fmt;    /* excluding c_fmt & len_fmt. 16 */
  40.     short monostereo;
  41.     short numchannels;
  42.     long samplerate;
  43.     long bytespersecond;
  44.     short bytespersample;
  45.     short bitspersample;
  46.  
  47.     char c_data[4];
  48.     long len_data;
  49. } wav_hdr;
  50.  
  51. static void stat8(unsigned char *p, int *_l, int *_u, int n) {
  52.     int l = 0, u = 0;
  53.     while (n--) {
  54.     int c;
  55.     c = ((int)*p++ - 0x80) << 8;
  56.     if (c < l)
  57.         l = c;
  58.     if (c > u)
  59.         u = c;
  60.     }
  61.     *_u = u;
  62.     *_l = l;
  63. }
  64.  
  65. static void stat16(short *p, int *_l, int *_u, int n) {
  66.     int l = 0, u = 0;
  67.     while (n--) {
  68.     if (*p < l)
  69.         l = *p;
  70.     if (*p > u)
  71.         u = *p;
  72.     ++p;
  73.     }
  74.     *_u = u;
  75.     *_l = l;
  76. }
  77.  
  78. #if 0
  79. static void wav_stat(void *data, const char *filename) {
  80.     int l, u;
  81.     printf("%s is %d bit %s at %ld Hz, %ld samples\n",
  82.        filename,
  83.        wav_hdr.bitspersample,
  84.        wav_hdr.monostereo != 1 ? "STEREO" : "MONO",
  85.        wav_hdr.samplerate,
  86.        wav_hdr.len_data);
  87.  
  88.     if (wav_hdr.monostereo != 1)
  89.     return;        /* cannot handle */
  90.     if (wav_hdr.bitspersample == 8)
  91.     stat8((unsigned char *)data, &l, &u, wav_hdr.len_data);
  92.     else if (wav_hdr.bitspersample == 16)
  93.     stat16((short *)data, &l, &u, wav_hdr.len_data / 2);
  94.     else
  95.     return;
  96.     {   double f1, f2, factor;
  97.     f1 = l < 0 ? -32768.0 / l : 65535.0;
  98.     f2 = u > 0 ?  32767.0 / u : 65535.0;
  99.     factor = f1 < f2 ? f1 : f2;
  100.     printf("min is -%04xH, max is %04xH, scale with %f for full amplitude\n", -l, u, factor);
  101.     }
  102. }
  103. #endif
  104.  
  105. static double abbreviation = 1.0;    /* playing speed factor */
  106. static double volumescale = 1.0;    /* volume scaling factor */
  107. static int writefile = 0;
  108.  
  109. static int fd_audio;
  110.  
  111. static void wav_play(unsigned char *data, long len, const char *filename) {
  112.     long i;
  113.     const char *fmt;
  114.     fmt = (wav_hdr.monostereo != 1) ? "STEREO" : "MONO";
  115.  
  116.     if ((fd_audio=open("/dev/dsp", O_WRONLY, 0)) == EOF) {
  117.     fprintf(stderr, "Cannot open /dev/dsp");
  118.     exit(1);
  119.     }
  120.  
  121.     /* speed adjust */
  122.     i = wav_hdr.samplerate;
  123.     wav_hdr.samplerate = (long)((double)wav_hdr.samplerate * abbreviation);
  124.     if (wav_hdr.samplerate > 22222) {
  125.     long j;
  126.     wav_hdr.samplerate /= 2;
  127.     len /= 2;
  128.     if (wav_hdr.bitspersample == 8)
  129.         for (j = 0; j < len; ++j)
  130.         data[j] = data[2*j];
  131.     else
  132.         for (j = 0; j < len; j += 2) {
  133.         data[j]   = data[2*j];
  134.         data[j+1] = data[2*j+1];
  135.         }
  136.     }
  137.  
  138.     /* volume scale */
  139.     if (wav_hdr.bitspersample == 16) {
  140.     /* 16 bit => 8 bit & scaling */
  141.     long j, clip = 0;
  142.     double new;
  143.     unsigned char *wr;
  144.     short *rd;
  145.     wr = data;
  146.     rd = (short *)data;
  147.     len /= 2;
  148.     for (j = 0; j < len; ++j) {
  149.         new = (*rd++ * volumescale) + 32768.0;
  150.         if (new < 0.0) {
  151.         new = 0.0;
  152.         ++clip;
  153.         } else if (new > 65535.5) {
  154.         new = 65535.0;
  155.         ++clip;
  156.         }
  157.         *wr++ = (unsigned char)(new / 256.0);
  158.         if (clip == 1) {
  159.         printf("warning: clipping at sample %ld\n", j);
  160.         ++clip;
  161.         }
  162.     }
  163.     if (clip)
  164.         printf("%ld samples clipped\n", clip-1);
  165.     wav_hdr.bytespersecond >>= 1;
  166.     wav_hdr.bytespersample >>= 1;
  167.     wav_hdr.bitspersample >>= 1;
  168.     wav_hdr.len_data >>= 1;
  169.     } else if (volumescale != 1.0) {
  170.     long j, clip = 0;
  171.     double new;
  172.     printf(" *** warning: volume scaling on 8 bit data may reduce quality ***\n");
  173.  
  174.     for (j = 0; j < len; ++j) {
  175.         new = ((double)data[j] - 128.0) * volumescale + 128.0;
  176.         if (new < 0.0) {
  177.         new = 0.0;
  178.         ++clip;
  179.         } else if (new >= 255.5) {
  180.         ++clip;
  181.         new = 255.0;
  182.         }
  183.         data[j] = (unsigned char)new;
  184.         if (clip == 1) {
  185.         printf("warning: clipping at sample %ld\n", j);
  186.         ++clip;
  187.         }
  188.     }
  189.     if (clip)
  190.         printf("%ld samples clipped\n", clip-1);
  191.     }
  192.     ioctl(fd_audio, SNDCTL_DSP_SPEED, &wav_hdr.samplerate);
  193. #if 0
  194.     printf("%8ld bytes (%s, %2d bits) %ld (%ld) Hz, file \"%s\", %d channels\n",
  195.        len, fmt, wav_hdr.bitspersample, i, wav_hdr.samplerate, filename,
  196.        wav_hdr.numchannels);
  197. #endif
  198.     if (wav_hdr.monostereo != 1)
  199.     return;        /* cannot handle */
  200.     write(fd_audio, data, len);
  201.     close(fd_audio);
  202.  
  203.     if (writefile) {
  204.     FILE *fp;
  205.     fp = fopen("/tmp/audio.wav", "wb");
  206.     fwrite(&wav_hdr, 1, sizeof(struct wavfmt), fp);
  207.     fwrite(data, 1, wav_hdr.len_data, fp);
  208.     fclose(fp);
  209.     }
  210. }
  211.  
  212. static void *readfile(const char *filename) {
  213.     int fd;
  214.     size_t cnt;
  215.     void *data;
  216.  
  217.     if ((fd = open(filename, O_RDONLY)) < 0) {
  218.     fprintf(stderr, "failed to open %s\n", filename);
  219.     return NULL;
  220.     }
  221.     if ((cnt = read(fd, &wav_hdr, sizeof(wav_hdr))) != sizeof(wav_hdr)) {
  222.     fprintf(stderr, "failed to read %s: only got %d byte\n", filename, cnt);
  223.     close(fd);
  224.     return NULL;
  225.     }
  226. #if 0
  227.     fprintf(stderr, "audio data length is %d byte\n", wav_hdr.len_data);
  228.     fprintf(stderr, "first bytes are %c%c%c%c \n",
  229.         wav_hdr.c_RIFF[0], wav_hdr.c_RIFF[1],
  230.         wav_hdr.c_RIFF[2], wav_hdr.c_RIFF[3]);
  231. #endif
  232.     if (!(data = malloc(wav_hdr.len_data))) {
  233.     fprintf(stderr, "not enough memory to read %s\n", filename);
  234.     close(fd);
  235.     return NULL;
  236.     }
  237.     /* read the data. This may loop */
  238.     {   int rest, this;
  239.     char *ptr;
  240.     rest = wav_hdr.len_data;
  241.     ptr = data;
  242.     while (rest && (this = read(fd, ptr, rest))) {
  243.         ptr += this;
  244.         rest -= this;
  245.     }
  246.     if (rest) {
  247.         fprintf(stderr, "cannot read chunk, %s\n", filename);
  248.         close(fd);
  249.         free(data);
  250.         return NULL;
  251.     }
  252.     }
  253.     close(fd);
  254.     return data;
  255. }
  256.  
  257. int main(int argc, char *argv[]) {
  258.     for (;;) {
  259.     void *data;
  260.     if (!(data = readfile("/tmp/audio")))
  261.         continue;
  262.     wav_play(data, wav_hdr.len_data, "/tmp/audio");
  263.     free(data);
  264.     }
  265.     return 0;
  266. }
  267.